﻿using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using IQToolkit;
using IQToolkit.Data;
using IQToolkit.Data.Common;
using Infrastucture.Helpers;
using MySql.Data.MySqlClient;

namespace Infrastucture.Factories
{
    public abstract class Factory<DataType, DomainType> : IFactory<DataType, DomainType>
    {
        protected readonly DbEntityProvider _provider;
        protected readonly IEntityTable<DataType> _db;
        private object _lock;


        public Factory(DbEntityProvider provider, IEntityTable<DataType> db)
        {
            _provider = provider;
            _db = db;
            
            _lock = new object();
        }

        public virtual DomainType CreateNew()
        {
            return Activator.CreateInstance<DomainType>();
        }

        public virtual DomainType Add(DomainType obj)
        {
            var dataObject = ModelConverter.ToModel<DataType>(obj);

            var keyValue = PropertyHelpers.GetPrimaryKeyValue(dataObject);

            if (keyValue == Guid.Empty)
            {
                keyValue = PropertyHelpers.SetPrimaryKeyValue(dataObject, Guid.NewGuid());

            }

            this.IsExecuting = true;
            int result = _db.InsertOrUpdate(dataObject);
            this.IsExecuting = false;
           



            return ModelConverter.ToModel<DomainType>(dataObject);
        }

        public virtual DomainType Save(DomainType obj)
        {
            var dataModel = ModelConverter.ToModel<DataType>(obj);

            this.IsExecuting = true;
            int result = _db.Update(dataModel);
            this.IsExecuting = false;
            

            return obj;
        }

        public virtual DomainType Upsert(DomainType obj)
        {
            var dataObject = ModelConverter.ToModel<DataType>(obj);
            var keyValue = PropertyHelpers.GetPrimaryKeyValue(dataObject);

            if (keyValue == Guid.Empty)
                return Add(obj);
            else
                return Save(obj);
        }

        public virtual DomainType Get(Func<DataType, bool> where)
        {
            var rec = Activator.CreateInstance<DataType>();

            this.IsExecuting = true;
            rec = _db.FirstOrDefault(where);
            this.IsExecuting = false;
            

            return ModelConverter.ToModel<DomainType>(rec);
        }

        public virtual List<DomainType> GetList()
        {
            List<DomainType> models = new List<DomainType>();

            List<DataType> recs = null;

            this.IsExecuting = true;
            recs = _db.ToList();
            this.IsExecuting = false;
            

            foreach (var r in recs)
            {
                var m = ModelConverter.ToModel<DomainType>(r);
                models.Add(m);
            }

            return models;
        }

        public virtual List<DomainType> GetList(Func<DataType, bool> where)
        {
            List<DomainType> models = new List<DomainType>();

            List<DataType> recs = null;



            this.IsExecuting = true;
            recs = _db.Where(where).ToList();
            this.IsExecuting = false;
            

            foreach (var r in recs)
            {
                var m = ModelConverter.ToModel<DomainType>(r);
                models.Add(m);
            }

            return models;
        }

        public bool IsExecuting { get; private set; }

        // connection helper
        private IEntityProvider getNewProvider()
        {
            string conn = "SERVER=127.0.0.1;DATABASE=timesplicer;UID=Rudy;PASSWORD=admin;";
            return DbEntityProvider.From("IQToolkit.Data.MySqlClient", conn, "TimeSplicerModule.Database.Timesplicer");
        }
    }
}
